<div id="app">{{title}}</div>

<script>
  // 填充代码
  // 1. 基本结构
  const Vue = {
    createApp(options) {
      // 返回app对象
      return {
        mount(selector) {
          // 1. 找到宿主元素
          const parent = document.querySelector(selector)
          // 2. 渲染页面
          if (!options.render) {
            // 2.1 处理template： 编译
            options.render = this.compile(parent.innerHTML)
          }

          // 收集 setup 和其他选项
          if (options.setup) {
            this.setupState = options.setup()
          }
          if (options.data) {
            this.data = options.data()
          }

          // 渲染之前，处理setup和其他选项的兼容
          const proxy = new Proxy(this, {
            get(target, key) {
              // 先从setup中取，如果取不到再从data中取
              // 如果setup存在，且key在setup中定义过
              if (target.setupState && key in target.setupState) {
                // return target.setupState[key]
                return Reflect.get(target.setupState, key)
              } else {
                // return target.data[key]
                return Reflect.get(target.data, key)
              }

            },
            set(target, key, val) {
              if (target.setupState && key in target.setupState) {
                return Reflect.set(target.setupState, key, val)
              } else {
                return Reflect.set(target.data, key, val)
              }
            }
          })


          // 2.2 用户直接编写render
          // 执行render函数（这里指定render函数中的this的上下文，是配置项中data函数的返回值）
          const el = options.render.call(proxy)

          // 3. 追加到宿主
          parent.innerHTML = ''
          parent.appendChild(el)
        },
        compile(template) {
          // 返回一个render函数
          // parse -> ast
          // generate: ast -> render
          return function render() {
            const h3 = document.createElement('h3')
            h3.textContent = this.title
            return h3
          }
        }
      }
    }
  }
</script>

<script>
  const app = Vue.createApp({
    data() {
      return {
        title: 'hello, vue3 YK菌 data'
      }
    },
    setup() {
      return {
        title: 'hello, vue3 YK菌 setup'
      }
    }
  })
  app.mount('#app')
</script>